
/*
 *  Copyright t lefering, David Given
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *  These are the four essential freedoms with GNU GPL software:
 *  1: freedom to run the program, for any purpose
 *  2: freedom to study how the program works, and change it to make it do what you wish
 *  3: freedom to redistribute copies to help your Free Software friends
 *  4: freedom to distribute copies of your modified versions to your Free Software friends
 *   ,           ,
 *  /             \
 * ((__-^^-,-^^-__))
 * `-_---'  `---_-'
 *  `--|o`   'o|--'
 *      \  `  /
 *       ): :(
 *       :o_o:
 *        "-"
 */

#include "globals.h"

static avltree_t pinfostore = NULL;

static int compare_cb(const void *lhs, const void *rhs)
{
	const struct pinfo *n1 = lhs;
	const struct pinfo *n2 = rhs;
	unsigned int i1 = 0;
	unsigned int i2 = 0;
#warning "args can be 0 "
	if (lhs && rhs) {
		i1 = (unsigned int)(size_t)n1->pseudo;
		i2 = (unsigned int)(size_t)n2->pseudo;
		if (i1 < i2)
			return -1;
		else if (i1 > i2)
			return 1;
	}
	return 0;
}

static void reset_cb(void *user)
{
	struct pinfo *pinfo = user;
	pinfo->reg.type = TYPE_NONE;
}

void reset_pinfo(void)
{
	avl_traverse(pinfostore, reset_cb);
	return;
}

struct pinfo *lookup_pinfo_of_pseudo(pseudo_t pseudo)
{
	struct pinfo key;
	struct pinfo *pinfo = NULL;

	if (pseudo == NULL) {
		return (NULL);
	}

	key.pseudo = pseudo;

	pinfo = avl_search(pinfostore, compare_cb, &key, 0);

	if (pinfo) {
		return pinfo;
	}

	pinfo = calloc(1, sizeof(struct pinfo));

	pinfo->pseudo = pseudo;
#warning "this starts avl crash"
	pinfo->type = lookup_base_type_of_pseudo(pseudo);

	switch (pinfo->type) {
	default:
		pinfo->size = 0;
		break;

	case TYPE_INT:
	case TYPE_FLOAT:
	case TYPE_FN:
		pinfo->size = bits_in_int;
		break;

	case TYPE_PTR:
	case TYPE_FNPTR:
		pinfo->size = bits_in_pointer;
		break;
	}

	avl_insert(&pinfostore, compare_cb, pinfo, NULL);
	return pinfo;
}
